package com.maltys.sign_aspect.aspect;

import com.maltys.sign_aspect.ErrorCode;
import com.maltys.sign_aspect.annotation.SignCheck;
import com.maltys.sign_aspect.configuration.GlobalConfiguration;
import com.maltys.sign_aspect.enums.SignTypeEnum;
import com.maltys.sign_aspect.util.SignContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;


/**
 * @author luonankun
 * @date 2022/10/21
 **/
@Aspect
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class SignCheckAspect {

    @Pointcut("@annotation(signCheck)")
    public void pointCut(SignCheck signCheck) {
    }

    @Before("pointCut(signCheck)")
    public void before(SignCheck signCheck) throws Exception {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();

        Boolean checkSign = new SignContext(signCheck.signType()).checkSign(request, deduceSignKey(signCheck), new int[2][2]);
        if (Boolean.FALSE.equals(checkSign)) {
            throw new Exception(signCheck.errorResponse().getMsg());
        }
    }

    public String deduceSignKey(SignCheck signCheck) {
        SignTypeEnum signTypeEnum = signCheck.signType();
        if (SignTypeEnum.SERVER == signTypeEnum) {
            return GlobalConfiguration.getServerSignKey();
        }
        log.warn("unknown sign type: [{}]", signTypeEnum.name());
        throw new SecurityException(ErrorCode.APP_SIGNATURE_ERROR.getMsg());
    }
}
